﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Threading;

namespace LjServer
{
    class TcpServer
    {
        static int m_Port = 40001;//服务端口
        public static Encoding m_EnCode = Encoding.UTF32;//通信息编码方式
        static List<StateObject> m_ClientWorkSockets = new List<StateObject>();//所有连接
        public static ManualResetEvent m_allDone = new ManualResetEvent(false);
        static int m_MaxListent = 100;//最大监听数

        /// <summary>
        /// 服务器开始监听
        /// </summary>
        public static void StartListening()
        {
            IPEndPoint _localEndPoint = new IPEndPoint(IPAddress.Any, m_Port);
            Socket _listener = new Socket(AddressFamily.InterNetwork,
                SocketType.Stream, ProtocolType.Tcp);
            try
            {
                _listener.Bind(_localEndPoint);
                _listener.Listen(m_MaxListent);

                while (true)
                {
                    m_allDone.Reset();
                    Console.WriteLine("[服务端]Waiting for a connection...");
                    _listener.BeginAccept(
                        new AsyncCallback(AcceptCallback),
                        _listener);
                    m_allDone.WaitOne();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
            Console.WriteLine("\n[服务端]Press ENTER to continue...");
            Console.Read();

        }
        public static void AcceptCallback(IAsyncResult ar)
        {
            m_allDone.Set();
            Socket _listener = (Socket)ar.AsyncState;
            Socket _handler = _listener.EndAccept(ar);
            StateObject state = new StateObject();
            state.workSocket = _handler;
            state.Handle = _handler.Handle;
            _handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
               new AsyncCallback(ReadCallback), state);
        }

        public static void ReadCallback(IAsyncResult ar)
        {
            string _content = string.Empty;
            StateObject _state = (StateObject)ar.AsyncState;
            Socket _handler = _state.workSocket;
            int _bytesRead = _handler.EndReceive(ar);
            if (_bytesRead > 0)
            {

                _content = m_EnCode.GetString(_state.buffer, 0, _bytesRead);
                int _sqlitIndex = _content.IndexOf('|');
                string _strState = _content.Substring(0, _sqlitIndex);
                string _Message = _content.Substring(_sqlitIndex + 1);
                Console.WriteLine(_content);
                if (_strState == "conect")//客户连接请求
                {
                    string[] _ipPoint = _Message.Split(':');
                    _state.Name = _Message;
                    _state.port = int.Parse(_ipPoint[1]);
                    string _nameMessage = string.Empty;
                    for (int i = 0; i < m_ClientWorkSockets.Count; i++)
                    {
                        if (_nameMessage == string.Empty)
                        {
                            _nameMessage = m_ClientWorkSockets[i].Name.Trim();
                        }
                        else
                        {
                            _nameMessage += "," + m_ClientWorkSockets[i].Name.Trim();
                        }
                    }
                    m_ClientWorkSockets.Add(_state);
                    if (_nameMessage != string.Empty)
                        Send(_handler, "Y|" + _nameMessage);

                    for (int i = 0; i < m_ClientWorkSockets.Count; i++)
                    {
                        Send(m_ClientWorkSockets[i].workSocket, "Y|" + _state.Name);
                    }

                }
                if (_strState == "send")
                {
                    _sqlitIndex = _Message.IndexOf('|');


                    string _ipPoint = _Message.Substring(0, _sqlitIndex);
                    string[] _ipFroms = _ipPoint.Split(',');

                    string _strSendMessage = _Message.Substring(_sqlitIndex + 1);
                    for (int i = 0; i < m_ClientWorkSockets.Count; i++)
                    {
                        if (m_ClientWorkSockets[i].Name == _ipFroms[0])
                        {
                            Send(m_ClientWorkSockets[i].workSocket, "msg|" + _ipFroms[1] + "|" + _strSendMessage);
                            break;
                        }
                    }
                }
                if (_strState == "request")
                {
                    _sqlitIndex = _Message.IndexOf('|');


                    string _ipFroms = _Message.Substring(0, _sqlitIndex);
                   
                    string _strSendMessage = _Message.Substring(_sqlitIndex + 1);
                    for (int i = 0; i < m_ClientWorkSockets.Count; i++)
                    {
                        if (m_ClientWorkSockets[i].Name == _ipFroms)
                        {
                            Send(m_ClientWorkSockets[i].workSocket, "msg|"  + _ipFroms[1] + "|" +_strSendMessage+"(From Server)");
                            break;
                        }
                    }
                }
                if (_strState == "close")
                {
                    for (int i = 0; i < m_ClientWorkSockets.Count; i++)
                    {
                        if (m_ClientWorkSockets[i].Handle == _handler.Handle)
                        {

                            m_ClientWorkSockets[i].workSocket.Shutdown(SocketShutdown.Both);
                            m_ClientWorkSockets[i].workSocket.Close();
                            m_ClientWorkSockets.Remove(m_ClientWorkSockets[i]);
                            break;
                        }
                    }

                    for (int i = 0; i < m_ClientWorkSockets.Count; i++)
                    {
                        Send(m_ClientWorkSockets[i].workSocket, "close|" + _Message);
                    }
                }
            }
            if (!_handler.Connected) return;
            _handler.BeginReceive(_state.buffer, 0, StateObject.BufferSize, 0,
                  new AsyncCallback(ReadCallback), _state);

        }
        public static void Send(Socket pWorkSocket, string pMessage)
        {
            Console.WriteLine();
            Console.WriteLine("[服务端]" + pMessage);
            byte[] _byteData = m_EnCode.GetBytes(pMessage);
            pWorkSocket.BeginSend(_byteData, 0, _byteData.Length, 0,
            new AsyncCallback(SendCallback), pWorkSocket);
        }
        private static void SendCallback(IAsyncResult ar)
        {
            try
            {
                Socket handler = (Socket)ar.AsyncState;
                int bytesSent = handler.EndSend(ar);
                Console.WriteLine("[服务端]Sent {0} bytes to client.", bytesSent);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        //add by roy on 2011-3-21
        public static void broadcast(string pMessage)
        {
            for (int i = 0; i < m_ClientWorkSockets.Count; i++)
            {

                Send(m_ClientWorkSockets[i].workSocket, "msg|" + AddressFamily.InterNetwork.ToString() + "|" + pMessage);
              
                
            }
        }
    }
}
